import { _decorator, Component, instantiate, Label, Node, Prefab, Tween, tween, UIOpacity } from 'cc';
import { DataProxy } from '../../../frame/A-LIB/sources/lib.b.data';
import { ClientAPI } from '../../api/api.client';
import GameDC from '../../data/data.game.center';
import DataManager from '../../manager/data.manager';
import { AudioManager } from '../../../frame/component/audio-manager';
const { ccclass, property } = _decorator;

@ccclass('LoadMain')
export class LoadMain extends Component {

	private lbl_state: Label;
	private lbl_progress: Label;

	private pages_list: Array<Promise<Node>>;
	private pre_load_tiles_np: mtec.NudityPromise<'end'>;

	private pro_ctrl: ProCtrl;

	protected onLoad() {
		this.init();
	}

	protected start() {
		ClientAPI.CloseLoading();
		this.adaptUI();
		this.initUIStatus();
	}

	private init(){
		this.lbl_state = this.node.getChildByName('lbl-state').getComponent(Label);
		this.lbl_progress = this.node.getChildByName('lbl-progress').getComponent(Label);
		this.lbl_state.string = 'Apple is not a sponsor nor is involved in any way\nwith these contests and sweepstakes';
		this.lbl_progress.string = 'LOADING...   ';
		this.pro_ctrl = new ProCtrl(5, 0, 0);
		this.pro_ctrl.setLabel(this.lbl_progress);
		this.pro_ctrl.updateProgress();
		this.loadPages();
		this.loadTiles();
	}

	private loadPages(){
		this.pages_list = ['home-bg', 'game', 'home-ui', 'treasurebox', 'achievement', 'transition', 'pop-up', 'guide', 'float']
		.map(name=>mtec.cc.loadResAsync('prefab/page/'+name, Prefab).then(prefab=>instantiate(prefab)));
	}

	private loadTiles(){
		this.pre_load_tiles_np = new mtec.NudityPromise();
		let reg = DataProxy.follow(GameDC.Trigger, 'PreLoadTiles', (_, status)=>{
			if(status==='end'){
				DataProxy.cancel(reg);
				this.pre_load_tiles_np.resolve('end');
				this.pro_ctrl.doneProgerss();
			}
		}, false);
		GameDC.Trigger.PreLoadTiles = 'start';
	}

	private adaptUI(){
		mtec.cc.adaptBackgroundNode(this.node.getChildByName('background'));
		let va_state = new mtec.cc.VecAssist(this.lbl_state.node);
		let va_progress = new mtec.cc.VecAssist(this.lbl_progress.node);

		va_state.getPosition('center', 'bottom');
		va_progress.getPosition('center', 'bottom');
		va_state.vec.add3f(0, 61, 0);
		va_progress.vec.add3f(0, 224, 0);
		this.lbl_state.node.setPosition(va_state.vec);
		this.lbl_progress.node.setPosition(va_progress.vec);
	}

	private initUIStatus(){
		let order_list = ['Camera', 'audio', 'home-bg', 'game', 'home-ui', 'treasurebox', 'achievement', 'transition', 'pop-up', 'guide', 'float', 'loading'];

		Promise.all(this.pages_list).then(pages=>{
			pages.forEach(p=>{
				p.active = false;
				p.setParent(this.node.parent);
			});

			order_list.forEach((name, i)=>{
				let p = this.node.parent.getChildByName(name);
				if(p){
					p.setSiblingIndex(i);
				}
			});
		}).then(()=>{
			this.pro_ctrl.doneProgerss();
			DataManager.oncePoint('GameInitFinish');
			return DataManager.LocalInited;
		}).then(()=>{
			this.pro_ctrl.doneProgerss();
			this.node.parent.children.forEach(n=>n.active = true);
		});

		DataManager.ConfigInited.then(()=>this.pro_ctrl.doneProgerss());
		DataManager.UserInfoSynced.then(()=>this.pro_ctrl.doneProgerss());

		this.pro_ctrl.DONE.then(()=>this.enterGame());
	}

	private enterGame(){
		DataManager.oncePoint('GameStart');

		let [background, logo] = ['background', 'logo'].map(name=>this.node.getChildByName(name));
		let [va_logo, va_state, va_progress] = [logo, this.lbl_state.node, this.lbl_progress.node].map(n=>new mtec.cc.VecAssist(n));

		let uiop = background.getComponent(UIOpacity);
		if(!uiop){
			uiop = background.addComponent(UIOpacity);
		}

		let duration = 0.5;
		tween(uiop).set({opacity: 255}).to(duration, {opacity: 0}, {easing: 'cubicOut'}).start();
		tween(background).to(duration, {scale: background.scale.clone().add3f(1, 1, 0)}, {easing: 'cubicOut'}).start();

		va_logo.vec.y = va_logo.over_top;
		va_state.getPosition('center', 'over_bottom');
		va_progress.getPosition('center', 'over_bottom');

		tween(logo).to(duration, {position: va_logo.vec}, {easing: 'cubicOut'}).start();
		tween(this.lbl_state.node).to(duration, {position: va_state.vec}, {easing: 'cubicOut'}).start();
		tween(this.lbl_progress.node).to(duration, {position: va_progress.vec}, {easing: 'cubicOut'}).start();

		GameDC.Trigger.LoadRound = GameDC.Cache.round_curr;
		GameDC.Trigger.UIHome = true;
		GameDC.Trigger.UIGame = true;

		this.scheduleOnce(()=>{
			this.node.destroy();
			AudioManager.playBGM();
		}, duration+0.1);
	}
}

class ProCtrl {
	private label: Label;
	private np: mtec.NudityPromise<'end'>;

	constructor(private _total_: number, private _done_: number, private _progress_: number){
		this.np = new mtec.NudityPromise();
	}

	public set progress(value: number){
		this._progress_ = value;
		this.label.string = 'LOADING...' + (Math.round(value) + '%').padStart(5, ' ');
	}
	public get progress(){
		return this._progress_;
	}

	public get DONE(){
		return this.np.promise;
	}

	public setLabel(label: Label){
		this.label = label;
	}

	public doneProgerss(){
		this._done_ = Math.min(this._done_+1, this._total_);
		this.updateProgress();
	}

	public updateProgress(){
		let done = this._done_ == this._total_;
		let progress = Math.min(1, (this._done_+1) / this._total_) * 100;
		Tween.stopAllByTarget(this);

		if(done){
			tween<ProCtrl>(this)
			.to(0.3, {progress: 100})
			.delay(0.5).call(()=>this.np.resolve('end'))
			.start();
		}else{
			tween<ProCtrl>(this).to(1, {progress}).start();
		}
	}
}
